<template>
  <div class>
    <!--添加弹出框-->
    <el-dialog title="文件上传" width="68%" top="20px" :visible.sync="dialogStatus" :close-on-click-modal="false" append-to-body :before-close="handleQx">
      <div style="display:flex;margin-bottom:5px;">
        <el-upload v-if="zjSx=='1'" class="upload-demo" :limit="limit" ref="upload" :action="action" :accept="accept" :data="data" :multiple="multiple" :show-file-list="showFileList" :on-exceed="handleExceed" :with-credentials="withcredentials" :before-upload="handleBeforeUpload" :on-progress="handleProgress" :on-success="handleSuccess" :on-error="handleError" :file-list="fileList">
          <el-button size="mini" type="primary" icon="el-icon-upload">普通附件</el-button>
        </el-upload>
        <el-upload v-if="zjSx=='1'" class="upload-demo" ref="upload1" :action="action" :multiple="false" :show-file-list="false" :before-upload="handleBeforeUploadBig" :on-error="handleErrorBig" :http-request="uploadSectionFile">
          <el-button size="mini" type="primary" icon="el-icon-upload2" style="margin-left:10px;">大文件上传</el-button>
        </el-upload>
      </div>
      <div slot="footer" class="dialog-footer">
        <el-button @click="handleQx()" size="small">取 消</el-button>
        <el-button type="primary" size="small" v-if="zjSx=='1'" @click="handleAdd()">确 定</el-button>
      </div>
      <el-table :data="tempArr" style="width: 100%" border height="350" size="small">
        <el-table-column type="index" align="center" label="序号" width="50"></el-table-column>
        <el-table-column prop="fileName" align="center" label="文件名" show-overflow-tooltip></el-table-column>

        <el-table-column prop="fileType" align="center" label="类型" width="100"></el-table-column>
        <el-table-column prop="progress" align="center" label="进度条" width="130">
          <template slot-scope="scope">
            <el-progress :percentage="scope.row.progress"></el-progress>
          </template>
        </el-table-column>
        <el-table-column prop="fileSize" align="center" label="大小" width="100"></el-table-column>
        <el-table-column align="center" label="操作" width="200">
          <template slot-scope="scope">
            <el-button v-if="readPower" @click="handlePreview(scope.$index, scope.row)" size="mini">预览</el-button>
            <el-button v-if="downPower" @click="handlePreviewD(scope.$index, scope.row)" size="mini">下载</el-button>
            <el-button v-if="zjSx=='1' || deletePower" @click="handleDelete(scope.$index, scope.row)" type="danger" size="mini">删除</el-button>
            <el-button @click="handleSearch(scope.$index, scope.row)" size="mini" type="success">记录</el-button>
          </template>
        </el-table-column>
      </el-table>
    </el-dialog>

    <el-dialog title :visible.sync="centerDialogVisible" width="70%" center>
      <show-img :list="urlList" />
    </el-dialog>

    <el-dialog title="操作记录" :visible.sync="czDialogVisible" center>
      <el-table :data="jLData" style="width: 100%" border height="350" size="small">
        <el-table-column type="index" align="center" label="序号" width="50"></el-table-column>
        <el-table-column prop="fileName" align="center" label="文件名" show-overflow-tooltip></el-table-column>
        <el-table-column prop="fileType" align="center" label="类型" width="90"></el-table-column>
        <el-table-column prop="fileSize" align="center" label="大小" width="90"></el-table-column>
        <el-table-column prop="createUserName" align="center" label="操作人" width="90"></el-table-column>
        <el-table-column prop="createTime" align="center" label="时间" width="150">
          <template slot-scope="scope">
            <div :title="scope.row.createTime==null?'':new Date(scope.row.createTime).toLocaleString()" class="overFlow">{{scope.row.createTime==null?'':new Date(scope.row.createTime).toLocaleString()}}</div>
          </template>
        </el-table-column>
      </el-table>
    </el-dialog>
  </div>
</template>

<script>
import showImg from "./showImg";
import SparkMD5 from "spark-md5";
export default {
  components: {
    showImg
  },
  data() {
    return {
      pageOfficeSx: "read", //	read	只读模式，不能修改、不能copy，不能打印。注意当使用此模式会导致当前电脑的copy复制功能都不能用。
      //edit可修改、保存、打印文档等所有操作。print 只读、可打印、可copy。也是系统默认模式
      zjSx: "1", //组件属性 0不可以删除 修改 只能预览 1:可以删除 修改 默认1
      limit: 20,
      action:
        this.baseURL +
        "/api/file/upload?Auth-User-Token=" +
        sessionStorage.getItem("token"),
      multiple: true, // 是否多选文件上传
      data: {}, // 上传时附带的额外参数
      showFileList: false, // 是否显示文件上传列表
      withcredentials: true, // 支持发送 cookie 凭证信息
      accept:
        ".jpg, .png, .txt, .zip, .rar,.avi,.mp4,.doc,.docx,.xlsx,.xls,.ppt,.pptx", // 接受上传的文件类型
      tempArr: [],
      fileList: [],
      dialogStatus: false,
      centerDialogVisible: false,
      urlList: [],
      jLData: [],
      czDialogVisible: false,
      chunkZhi: "16", //切块大小值 默认按照8M来切
      //======权限==============
      readPower:true,
      downPower:false,
      deletePower:false,
    };
  },

  mounted() {},
  computed: {},
  watch: {},
  methods: {
    init(){

    },

    //确定按钮
    handleAdd() {
      this.$refs.upload.uploadFiles = [];
      this.$emit("sendmsg", this.tempArr);
      this.dialogStatus = false;
    },
    //取消按钮
    handleQx() {
      this.$refs.upload.uploadFiles = [];
      this.fileList = [];
      this.tempArr = [];
      this.dialogStatus = false;
    },
    //打开组件弹框
    open(v,typeDetailId,masterId) {
      if (v == "") {
        this.tempArr = [];
        this.dialogStatus = true;
      } else {
        let params = {
          arr: JSON.stringify(v)
        };
        this.$api
          .formPost("/api/biz/file/fileUpfile/doGetListByZhi", params)
          .then(res => {
            if (res.retHead.code == "0000000") {
              if (res.retBody == "") {
                this.tempArr = [];
              } else {
                this.tempArr = res.retBody;
              }
              this.dialogStatus = true;
            } else {
              this.$message({
                message: "查询失败！",
                type: "error"
              });
            }
          });

        if(this.tempArr!=[]&&typeDetailId&&zjSx=="0"&&masterId){
          let user = JSON.parse(sessionStorage.getItem("user"));
          let params1={
            projMateId: typeDetailId,
            userId: user.userId,
            masterId:masterId
          };
          this.$api.formPost("/api/biz/baseMateAuth/doGetListByUserId", params)
          .then(res => {
            if (res.retHead.code == "0000000") {
              if (res.retBody != "") {
                let powers = res.retBody;
                powers.forEach( el => {
                  if(el==1){
                    this.readPower=true;
                    pageOfficeSx="read";
                  }else if(el==2){
                    this.readPower=true;
                    pageOfficeSx="print";
                  }else if(el==3){
                    this.downPower=true;
                  }else if(el==4){
                    this.readPower=true;
                    pageOfficeSx="edit";
                  }else if(el==5){
                    this.deletePower=true;
                  }
                });
                
              }
            } else {
              this.$message({
                message: "查询失败！",
                type: "error"
              });
            }
          });
        }  
      }
    },
    /**
     * 文件超出个数限制时的钩子
     */
    handleExceed(files, fileList) {
      if (fileList.length >= this.limit || fileList == "") {
        this.$message.error("最多允许上传" + this.limit + "个文件");
        return false;
      }
    },

    /**
     * 文件上传前的钩子，可以做一些拦截
     * return false,则停止上传
     */
    handleBeforeUpload(file) {
      // 文件大小限制
      const isLt5M = file.size / 1024 / 1024 < 100;
      if (!isLt5M) {
        this.$message.error("文件上传不得超过100M");
        return isLt5M;
      }
      // 文件类型限制
      const name = file.name ? file.name : "";
      const ext = name
        ? name.substr(name.lastIndexOf(".") + 1, name.length)
        : true;
      const isExt = this.accept.indexOf(ext) < 0;
      if (isExt) {
        this.$message.error("请上传正确的格式类型");
        return !isExt;
      }
      var index = file.name.lastIndexOf(".");
      var fileName = file.name.substring(0, index);
      var fileType = file.name.substring(index, file.name.length);
      // 大小和类型验证都通过后，给自定义的列表中添加需要的数据
      const tempObj = {
        uid: file.uid, // uid用于辨别文件
        fileName: fileName, // 列表显示的文件名
        fileType: fileType,
        progress: 0, // 进度条,
        fileSize: this.formateSize(file.size)
      };
      this.tempArr.push(tempObj);
    },

    /**
     * 大文件文件上传前的钩子，可以做一些拦截
     * return false,则停止上传
     */
    handleBeforeUploadBig(file) {
      // 文件大小限制
      const isLt5M = file.size / 1024 / 1024 < 100;
      if (isLt5M) {
        this.$message.error("大文件上传不得低于100M,请使用普通附件上传");
        return false;
      }
      // 文件类型限制
      const name = file.name ? file.name : "";
      const ext = name
        ? name.substr(name.lastIndexOf(".") + 1, name.length)
        : true;
      const isExt = this.accept.indexOf(ext) < 0;
      if (isExt) {
        this.$message.error("请上传正确的格式类型");
        return !isExt;
      }
      var index = file.name.lastIndexOf(".");
      var fileName = file.name.substring(0, index);
      var fileType = file.name.substring(index, file.name.length);
      // 大小和类型验证都通过后，给自定义的列表中添加需要的数据
      const tempObj = {
        uid: file.uid, // uid用于辨别文件
        fileName: fileName, // 列表显示的文件名
        fileType: fileType,
        progress: 0, // 进度条,
        fileSize: this.formateSize(file.size)
      };
      this.tempArr.push(tempObj);
    },

    /**
     * 文件上传时的钩子
     */
    handleProgress(event, file, fileList) {
      this.tempArr.forEach((element, index) => {
        if (element.uid === file.uid) {
          // 更新这个uid下的进度
          const progress = Math.floor(event.percent);
          // 防止上传完接口还没有返回成功值，所以此处给定progress的最大值为99，成功的钩子中再置为100
          element.progress = progress === 100 ? 99 : progress;
          this.$set(this.tempArr, index, element);
        }
      });
    },
    /***
     * 文件上传成功时
     */
    handleSuccess(response, file, fileList) {
      const bizCode = response.retHead.code;
      switch (bizCode) {
        case "0000000":
          this.tempArr.forEach((element, index) => {
            if (element.uid === file.uid) {
              element.progress = 100;
              element.fileHash = response.retBody.fileHash;
              let user = JSON.parse(sessionStorage.getItem("user"));
              let param = {
                fileName: element.fileName,
                fileSize: element.fileSize,
                fileType: element.fileType,
                progress: 100,
                fileHash: response.retBody.fileHash,
                createUserId: user.id,
                createUserName: user.username
              };
              this.$api
                .formPost("/api/biz/file/fileUpfile/doSubmit", param)
                .then(res => {
                  if (res.retHead.code == "0000000") {
                    element.id = res.retBody;
                    this.$message.success("文件上传成功");
                    
                    this.$refs.upload.uploadFiles.forEach((item, index) => {
                      if (item.uid === element.uid) {
                        this.$refs.upload.uploadFiles.splice(index, 1);
                      }
                    });
                    this.$set(this.tempArr, index, element);
                  } else {
                    this.tempArr.forEach((element, index) => {
                      if (element.uid === file.uid) {
                        this.tempArr.splice(index, 1); // 上传失败删除该记录
                        this.$message.error("文件上传失败");
                      }
                    });
                  }
                });
            }
          });
          break;
        default:
          this.tempArr.forEach((element, index) => {
            if (element.uid === file.uid) {
              this.tempArr.splice(index, 1); // 上传失败删除该记录
              this.$message.error("文件上传失败");
            }
          });
          break;
      }
    },
    /***
     * 文件上传失败删除该项
     */
    handleError(err, file, fileList) {
      this.tempArr.forEach((element, index) => {
        if (element.uid === file.uid) {
          this.tempArr.splice(index, 1); // 上传失败删除该记录
          this.$message.error("文件上传失败");
        }
      });
    },
    /***
     * 大文件上传失败删除该项
     */
    handleErrorBig(err, file, fileList) {
      this.tempArr.forEach((element, index) => {
        if (element.uid === file.uid) {
          this.tempArr.splice(index, 1); // 上传失败删除该记录
          this.$message.error("文件上传失败");
        }
      });
    },

    //上传文件方法
    uploadSectionFile(param) {
      //获取总文件的md5
      this.getFileMD5(param.file, md5 => {
        //执行上传方法
        this.funA(param.file, md5);
      });
    },
    funA(file, fileMd5) {
      const _this = this;
      var currentChunk = 0;
      // 上传文件块的大小，可自定义
      var chunkSize = 1024 * 1024 * parseInt(this.chunkZhi);
      // 计算改文件的可分为多少块
      var chunks = Math.ceil(file.size / chunkSize);
      let fd = new FormData();
      // 设置文件上传接口的需要的参数
      var fileType = file.name.split(".");
      fileType = fileType[fileType.length - 1].toLowerCase();
      let param = {
        fileName: file.name,
        aliases: file.name,
        fileType: fileType,
        fileHash: fileMd5,
        fileSize: file.size,
        chunkSize: chunkSize
      };
      _this.$api.formPost("/api/file/crewfid", param).then(res => {
        console.log(res);
        if (res.retHead.code == "0000000") {
          var fileid = res.retBody.id;
          //表示已经上传过了
          if (res.retBody.fileStatus == "1") {
            //入库
            _this.toRk(file, res, fileMd5);
          } else {
            //否则进行切块
            //没有上传过的文件 切块上传
            var fileReader = new FileReader();
            if (file.size > chunkSize) {
              //将文件进行分块 file.slice(start,length)
              var data1 = file.slice(0, parseInt(chunkSize));
              //将文件读取为二进制码
              fileReader.readAsArrayBuffer(data1);
            } else {
              fileReader.readAsArrayBuffer(file);
            }
            //文件读取完毕之后的处理
            var spark = new SparkMD5();
            fileReader.onload = function(e) {
              var md51 = SparkMD5.ArrayBuffer.hash(e.target.result);
              let param = {
                fileHash: md51,
                wholeFileId: fileid,
                chunkNum: currentChunk
              };
              _this.$api.formPost("/api/file/check/", param).then(res => {
                // 后台返回没有上传过
                if (res.retHead.code == "0000000") {
                  if (res.retBody == false) {
                    // 用FormData传输文件对象
                    let fd1 = new FormData();
                    // 设置文件上传接口的需要的参数
                    fd1.append("aliases", file.name);
                    fd1.append("chunkNum", currentChunk);
                    fd1.append("wholeFileId", fileid);
                    console.log(currentChunk);
                    // 设置上传的当前的文件块
                    fd1.append("file", new Blob([this.result]));
                    var progress = parseInt(
                      (e.loaded + currentChunk * chunkSize) / file.size * 100
                    );
                    _this.getProgress(file, progress);
                    _this.$api
                      .formDataPost("/api/file/upload", fd1)
                      .then(res => {
                        if (res.retHead.code == "0000000") {
                          currentChunk++;
                          if (parseInt(currentChunk) < parseInt(chunks)) {
                            var start = currentChunk * chunkSize,
                              end = Math.min(start + chunkSize, file.size);
                            // 切割文件并触发fileReader.onload
                            fileReader.readAsArrayBuffer(
                              file.slice(start, end)
                            );
                          } else {
                            // 文件上传成功入库
                            _this.toRk(file, res, fileMd5);
                          }
                        } else {
                          _this.tempArr.forEach((element, index) => {
                            if (element.uid === file.uid) {
                              _this.tempArr.splice(index, 1); // 上传失败删除该记录
                              _this.$message.error(
                                "文件上传失败" + res.retBody
                              );
                            }
                          });
                          return;
                        }
                      });
                    // 后台返回此块已经上传过继续判断下一块文件块
                  } else {
                    currentChunk++;
                    if (currentChunk < parseInt(chunks)) {
                      var start = currentChunk * chunkSize,
                        end = Math.min(start + chunkSize, file.size);
                      // 切割文件并触发fileReader.onload
                      fileReader.readAsArrayBuffer(file.slice(start, end));
                    }
                  }
                } else {
                  _this.tempArr.forEach((element, index) => {
                    if (element.uid === file.uid) {
                      _this.tempArr.splice(index, 1); // 上传失败删除该记录
                      _this.$message.error("文件上传失败" + res.retBody);
                    }
                  });
                  return;
                }
              });
            };
          }
        } else {
          this.$message.error("上传失败，失败原因为" + res.retBody);
          return;
        }
      });
    },
    /**
     * 获取进度条
     */
    getProgress(file, progress) {
      this.tempArr.forEach((element, index) => {
        if (element.uid === file.uid) {
          element.progress = progress;
          this.$set(this.tempArr, index, element);
        }
      });
    },
    /**
     * 文件上传成功调用方法
     */
    toRk(file, res, fileMd5) {
      this.tempArr.forEach((element, index) => {
        if (element.uid === file.uid) {
          element.progress = 100;
          element.fileHash = fileMd5;
          let user = JSON.parse(sessionStorage.getItem("user"));
          let param = {
            fileName: element.fileName,
            fileType: element.fileType,
            progress: 100,
            fileSize: element.fileSize,
            fileHash: fileMd5,
            createUserId: user.id,
            createUserName: user.username
          };
          this.$api
            .formPost("/api/biz/file/fileUpfile/doSubmit", param)
            .then(res => {
              if (res.retHead.code == "0000000") {
                element.id = res.retBody;
                this.$message.success("文件上传成功");
                this.$set(this.tempArr, index, element);
              } else {
                this.toDelete(file, res);
              }
            });
        }
      });
    },
    /**
     * 文件上传失败处理逻辑（方法），此方法不是组件中 而是上传过程中出现分问题
     */
    toDelete(file, res) {
      this.tempArr.forEach((element, index) => {
        if (element.uid === file.uid) {
          this.tempArr.splice(index, 1); // 上传失败删除该记录
          this.$message.error("文件上传失败" + res.retBody);
        }
      });
    },
    //获取文件的md5
    getFileMD5(file, callback) {
      //声明必要的变量
      var fileReader = new FileReader(),
        //文件每块分割，计算分割详情
        chunkSize = 1024 * 1024 * parseInt(this.chunkZhi),
        chunks = Math.ceil(file.size / chunkSize),
        currentChunk = 0,
        spark = new SparkMD5();
      var start = currentChunk * chunkSize,
        end = start + chunkSize >= file.size ? file.size : start + chunkSize;
      fileReader.readAsBinaryString(file.slice(start, end));
      //每块文件读取完毕之后的处理
      fileReader.onload = function(e) {
        //每块交由sparkMD5进行计算
        spark.appendBinary(e.target.result);
        currentChunk++;
        //如果文件处理完成计算MD5，如果还有分片继续处理
        if (currentChunk < chunks) {
          var start = currentChunk * chunkSize,
            end =
              start + chunkSize >= file.size ? file.size : start + chunkSize;
          fileReader.readAsBinaryString(file.slice(start, end));
        } else {
          callback(spark.end());
        }
      };
    },
    /**
     * 列表删除文件
     */
    handleDelete(index, row) {
      this.$confirm("此操作将永久删除该项, 是否继续?", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning"
      })
        .then(() => {
          if (row.uid == null) {
            this.$message({
              message: "操作成功！",
              type: "success"
            });
            this.tempArr.splice(index, 1); // 上传失败删除该记录
          } else {
            this.$api
              .formPost("/api/biz/file/fileUpfile/doRmById", {
                id: row.id
              })
              .then(res => {
                if (res.retHead.code == "0000000") {
                  this.$message({
                    message: "操作成功！",
                    type: "success"
                  });
                  this.tempArr.splice(index, 1); // 上传失败删除该记录
                  // this.$refs.upload.uploadFiles.forEach((element, index) => {
                  //   if (element.uid === row.uid) {
                  //     this.$refs.upload.uploadFiles.splice(index, 1);
                  //   }
                  // });
                } else {
                  this.$message({
                    message: "操作失败！",
                    type: "error"
                  });
                }
              });
          }
        })
        .catch(() => {
          this.$message({
            type: "info",
            message: "已取消删除"
          });
        });
    },
    /**
     *预览文件
     */
    handlePreview(index, row) {
      let that = this;
      this.urlList = [];
      if (/\.(png|jpg|gif|jpeg)$/.test(row.fileType)) {
        //图片类型的话：1.先要在数组里面放入当前点击的图片
        // 2.然后在获取到列表中其它的图片
        this.urlList.push({
          src:
            this.baseURL +
            "/api/file/downloadFile/" +
            row.fileHash +
            "?Auth-User-Token=" +
            sessionStorage.getItem("token")
        });
        this.tempArr.forEach(item => {
          if (/\.(png|jpg|gif|jpeg)$/.test(item.fileType)) {
            if (item.id != row.id) {
              this.urlList.push({
                src:
                  this.baseURL +
                  "/api/file/downloadFile/" +
                  item.fileHash +
                  "?Auth-User-Token=" +
                  sessionStorage.getItem("token")
              });
            }
          }
        });
        this.centerDialogVisible = true;
      } else if (/\.(doc|docx|xls|xlsx|ppt|pptx)$/.test(row.fileType)) {
        //如果是word excel类型 要获取文件最新一条的hsah值
        let params = {
          id: row.id
        };
        this.$api
          .formPost("/api/biz/file/fileUpfile/doGetFileUpfile", params)
          .then(res => {
            if (res.retHead.code == "0000000") {
              var shuju = res.retBody;
              console.log(shuju.fileHash);
              let user = JSON.parse(sessionStorage.getItem("user"));
              let token = sessionStorage.getItem("token");
              var fileType = shuju.fileType.replace(".", "");
              var url = encodeURI(
              	"http://115.233.221.131:28082/api/pageoffice/openFile?fileHash=" +
                  shuju.fileHash +
                  "&operator=" +
                  this.pageOfficeSx +
                  "&fileId=" +
                  shuju.id +
                  "&fileName=" +
                  shuju.fileName +
                  "&fileType=" +
                  fileType +
                  "&token=" +
                  token +
                  "&createUserId=" +
                  user.id +
                  "&createUserName=" +
                  user.username
              );
              POBrowser.openWindowModeless(url, "width=1200px;height=800px;");
              console.log(res.retBody);
            } else {
              this.$message({
                message: "查询失败！",
                type: "error"
              });
            }
          });
      } else {
        //其他类型的文件直接下载
        var xzUrl =
          this.baseURL +
          "/api/file/downloadFile/" +
          row.fileHash +
          "?Auth-User-Token=" +
          sessionStorage.getItem("token");
        window.location.href = xzUrl;
      }
    },
    
    /**
     *下载文件
     */
    handlePreviewD(index, row) {
      let that = this;
      this.urlList = [];
      //其他类型的文件直接下载
      var xzUrl =
        this.baseURL +
        "/api/file/downloadFile/" +
        row.fileHash +
        "?Auth-User-Token=" +
        sessionStorage.getItem("token");
      window.location.href = xzUrl;
    },
    //操作记录
    handleSearch(index, row) {
      let param = {
        id: row.id
      };
      this.$api
        .formPost("/api/biz/file/fileUpfile/doGetListById", param)
        .then(res => {
          if (res.retHead.code == "0000000") {
            this.jLData = res.retBody;
            this.czDialogVisible = true;
          } else {
            this.$message({
              message: "查询失败！",
              type: "error"
            });
          }
        });
    },
    /*
     * 格式化文件大小显示
     * value : file文件的大小值
     * */
    formateSize(value) {
      if (null == value || value == "") {
        return "0 Bytes";
      }
      var unitArr = new Array(
        "Bytes",
        "KB",
        "MB",
        "GB",
        "TB",
        "PB",
        "EB",
        "ZB",
        "YB"
      );
      var index = 0;
      var srcsize = parseFloat(value);
      index = Math.floor(Math.log(srcsize) / Math.log(1024));
      var size = srcsize / Math.pow(1024, index);
      size = size.toFixed(2); //保留的小数位数
      return size + unitArr[index];
    }
  },
  created() {}
};
</script>
<style lang='scss' scoped>
.btns {
  text-align: right;
}
.icon-arrow {
  position: absolute;
  bottom: 5px;
  left: 0;
  width: 100%;
  height: 1px;
  background-color: #f1f1f1;
  i {
    background-color: #fff;
    position: absolute;
    color: #999;
    bottom: -7px;
    margin-left: 50%;
    transform: translateX(-50%);
    cursor: pointer;
  }
}
</style>